/*
 * @version: 1.0
 * @Author: zhl
 * @Date: 2021-09-02 17:12:33
 * @LastEditors: zhl
 * @LastEditTime: 2021-09-02 17:53:27
 * @Description: file content
 */

#include <stdlib.h>
#include <stdio.h>
#include "threadPool.h"


T_THREAD_INFO* g_thread_pool = NULL;
int  g_thread_cnt = 0;


void threadPoolDestroy(){
	if(NULL != g_thread_pool){
		for(int i = 0; i < g_thread_cnt; i++){
			pthread_join(g_thread_pool[i].m_thread, NULL);
		}
		free(g_thread_pool);
	}
}

void* threadPoolFunc(void* arg) {
	if(NULL == arg){
		return NULL;
	}
	T_THREAD_INFO* thread_info = (T_THREAD_INFO*)arg;
	while (1) {
		threadLockLock(&thread_info->m_lock);

		while(NULL == thread_info->m_task_list){
			threadLockWait(&thread_info->m_lock);
		}
		T_TASK* pTask = thread_info->m_task_list;
		thread_info->m_task_list = pTask->next;
		thread_info->m_task_list->prev = NULL;
		threadLockLock(&thread_info->m_lock);
		pTask->run();
		if(pTask == thread_info->m_task_list_tail){
			thread_info->m_task_list_tail = NULL;
		}
		if(NULL != pTask->data.data){
			free(pTask->data.data);
			pTask->data.len = 0;
		}
		free(pTask);
	}
	return NULL;
}

/**
 * @function: 初始化线程池
 * @param   : num 线程池中线程数量
 */
int threadPoolInit(int num){
	if(1 > num){
		num = 1;
	}
	threadPoolDestroy();
	g_thread_cnt = num;
	g_thread_pool = (T_THREAD_INFO*)malloc(sizeof(T_THREAD_INFO));
	for(int i = 0; i < g_thread_cnt; i++){
		g_thread_pool[i].m_task_list = NULL;
		g_thread_pool[i].m_thread_idx = i;
		g_thread_pool[i].m_task_list_tail = NULL;
		if(0 == threadLockInit(&g_thread_pool[i].m_lock)){
			pthread_create(&g_thread_pool[i].m_thread, NULL, threadPoolFunc, g_thread_pool+i);
		}
	}
}

int getThreadIdx(){
	srand((unsigned)time(NULL));
    return (rand() % g_thread_cnt);
}
/**
 * @function: 向线程池中添加任务
 */
void push_task(T_TASK* task) {
	if(NULL == task){
		return;
	}
	int idx = getThreadIdx();
	threadLockLock(&g_thread_pool[idx].m_lock);
	if(NULL == g_thread_pool[idx].m_task_list_tail){
		g_thread_pool[idx].m_task_list_tail = task;
		g_thread_pool[idx].m_task_list = g_thread_pool[idx].m_task_list_tail;
	} else {
		g_thread_pool[idx].m_task_list_tail->next = task;
		task->prev = g_thread_pool[idx].m_task_list_tail;
		g_thread_pool[idx].m_task_list_tail = g_thread_pool[idx].m_task_list_tail->next;
	}
	threadLockSignal(&g_thread_pool[idx].m_lock);
	threadLockUnlock(&g_thread_pool[idx].m_lock);
}
